﻿#if !Profile && KVDB
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using O1.Kernel.Storage;
using O1.Kernel.Storage.Transactions;

namespace O1.Profiling
{
    class Program
    {
#if !DEBUG
        private const int size = 1024 * 10; //24;// * 10;
#endif
#if DEBUG
        private const int size = 1;
#endif

        private const int MaxCellSz = 4096;

        private static readonly string connString = ConfigurationManager.ConnectionStrings["SqlKvDb"].ConnectionString;

        // effect of padding? will spill to the next 16 byte boundary once 8 bytes are exceeded, requires 8 bytes of memory overhead for malloc

        static void Main(string[] args)
        {
            var proc = Process.GetCurrentProcess();
            var bytesAllocated = proc.WorkingSet64;

            Console.Write("Before allocation..." + bytesAllocated);
            Console.ReadLine();

            var stopwatch = Stopwatch.StartNew();

            Console.WriteLine("Allocated " + size + " trunk storage.");
            Console.WriteLine("...in " + stopwatch.ElapsedMilliseconds + " milliseconds.");

            Console.Write("Before cell population...");
            Console.ReadLine();

            stopwatch.Restart();
            for(int i = 0; i < size; i++)
            {
               WriteCell(i, new byte[Math.Max(i % MaxCellSz, 16)], null);
            }

            for (int i = 0; i < size; i++)
            {
                int version;
                var data = ReadCell(i, out version);
                data = ReadCell(i, out version);
                // data[0] = 255;

                // WriteCell(i, new byte[Math.Max(i % MaxCellSz, 16)], version);
            }

            Console.Write("Allocated, Read and updated " + size + " cells ");
            Console.WriteLine("...in " + stopwatch.ElapsedMilliseconds + " milliseconds.");
            Console.ReadLine();
        }

        private static void WriteCell(long key, byte[] data, int? version)
        {
            using (var connection = new SqlConnection(connString))
            {
                connection.Open();
                var handle = new KvDbApi.ValueHandle(key.ToString()) { HardenToDisk = false, Version = version };
                using (var m = handle.GetWriterStream(connection))
                {
                    m.Write(data, 0, data.Length);
                    m.Flush();
                }
            }
        }

        private static byte[] ReadCell(long key, out int version)
        {
            using (var connection = new SqlConnection(connString))
            {
                var handle = new KvDbApi.ValueHandle(key.ToString()) { HardenToDisk = false };
                byte[] data = null;
                using (var reader = handle.GetReaderStream(connection))
                using (var m = new MemoryStream(8192))
                {
                    reader.CopyTo(m, 8192);
                    data = m.ToArray();
                }

                version = handle.Version.Value;
                return data;
            }
        }
    }
}

#endif